/*
 * 原版接口
 */
import * as server_ui from "@minecraft/server-ui";
import * as server from "@minecraft/server";
/*
 * 系统数据
 */
import * as data_format from "../data/format";
import * as data_entity from "../data/entity";
import * as data_speak from "../data/speak";
import * as data_story from "../data/story";
import * as data_item from "../data/item";
/*
 * 系统组件
 */
import * as power_property from "../system/power_property";
import * as derived_tools from "../system/derived_tools";
import * as native_tools from "../system/native_tools";
import * as achieve_plan from "../system/achieve_plan";
import * as math_tools from "../system/math_tools";
/*
 * 物品组件
 */
import * as tool_component from "../item/tool_component";
/*
 * 实体组件
 */
import * as passive_component from "./passive_component";
/**
 * * 角色台词与语音管理器
 */
export class RoleSpeechAndVoiceManager extends achieve_plan.Template {
    public afterPlanEvent(data: achieve_plan.AFTER_PLAN_DATA) {
        /**
         * * 台词 的 类型
         */
        const type = this.annex.other?.type;
        /**
         * * 播放台词 的 角色
         */
        const entity = this.annex.self;
        // 验证参数
        if (!type || !entity || !entity.isValid()) return data.remove();
        // 判断 角色台词是否允许播报
        if (!achieve_plan.ControlEventTrigger.EntityToken('神恩领航者台词', entity, 1200)) return data.remove();
        /** 
         * * 设置广播范围
         */
        const options: server.EntityQueryOptions = {
            location: entity.location,
            maxDistance: 8
        };
        /**
         * * 角色类型标签
         */
        const typeTag = entity.typeId.split(/:/)[1];
        /**
         * * 角色台词库
         */
        const content = data_speak.compile.get(typeTag)?.get(type) ?? data_speak.defaultSpeak;
        /**
         * * 随机台词索引
         */
        const index = Math.floor(Math.random() * (content.length - 1));
        /**
         * * 获取玩家队列
         */
        const players = entity.dimension.getPlayers(options);
        /**
         * * 构建文本信息
         */
        const rawMessage = [native_tools.EntityTranslate(entity), { text: ' : ' }, content[index]];
        /**
         * * 角色语音标签
         */
        const soundTag = 'speak.' + typeTag + '.' + type + '_' + index;
        // 判断周围有效的玩家数量
        if (players.length == 0) return data.remove();
        // 遍历玩家队列
        players.forEach(
            player => {
                // 验证玩家是否有效
                if (!player.isValid()) return;
                // 显示文本信息
                player.sendMessage(rawMessage);
                // 播放 角色语音
                player.playSound(soundTag);
            }
        );
        // 移除 当前计划
        return data.remove();
    };
    public beforePlanEvent(data: achieve_plan.BEFORE_PLAN_DATA) {
        if (data.plan.annex.other?.type == 'routine' && data.plan.cooldown == 1) {
            // 设定 当前计划表 等待时间
            data.plan.cooldown += (achieve_plan.Control.inventory.length * math_tools.Random({ min: 1, max: 100 }, true));
            // 暂停 当前计划的执行
            data.cease();
        }
    };
};
/**
 * * 显示生命值变动
 * 
 * @param {server.Entity} entity - 生命值变动的实体
 * 
 * @param {number} input - 生命值变动的数值
 */
export function HealthAlterDisplay(entity: server.Entity, input: number) {
    /**
     * * 获取 基础偏移量
     */
    const getOffset = data_entity.offset_show.get(entity.typeId) ?? 1.5;
    /**
     * * 随机生成 偏移量
     */
    const createPlace: server.Vector3 = { x: (Math.random() * 2) - 1, y: getOffset, z: (Math.random() * 2) - 1 };
    // 当 生命值变动 在 99999 以上时 不显示
    if (Math.abs(input) >= 99999) return;
    /**
     * * 生命值变动方向
     */
    const direction = input >= 0 ? 0 : 1;
    // 保证显示值为自然数
    input = Math.abs(input);
    /**
     * * 获得 实体属性面板
     */
    const data = power_property.GetProperty(entity);
    /**
     * * 粒子参数
     */
    const molang = new server.MolangVariableMap();
    /**
     * * 数值信息
     */
    const array = input.toString().split('').reverse().map(value => parseInt(value, 10));
    /**
     * * 获取 颜色
     */
    const colour = data_story.getRuneColor(data.add_rune);
    // 设定 粒子参数
    molang.setVector3('variable.offset', createPlace);
    molang.setColorRGB('variable.color', colour);
    // 显示 数值
    array.forEach(
        (value, index) => {
            // 设定 粒子参数
            molang.setVector3('variable.property', { x: value, y: index, z: array.length });
            // 显示 数字粒子
            native_tools.TrySpawnParticle(entity.dimension, 'scripts:number_display', entity.location, molang);
        }
    );
    // 设置 粒子参数
    molang.setVector3('variable.property', { x: direction, y: array.length - 1, z: array.length });
    // 显示 符号粒子
    native_tools.TrySpawnParticle(entity.dimension, 'scripts:symbol_display', entity.location, molang);
};
/**
 * * 创建 实体契约绑定
 * 
 * @param {server.Entity} object - 进行契约的实体
 */
export function CreateContract(object: server.Entity) {
    /**
     * * 设定查询参数
     */
    const options: server.EntityQueryOptions = {
        location: object.location,
        maxDistance: 16,
        closest: 1
    };
    /**
     * * 进行操作的玩家
     */
    const player = object.dimension.getPlayers(options)[0];
    /**
     * * 玩家名称
     */
    const userName = native_tools.EntityTranslate(player);
    /**
     * * 角色名称
     */
    const roleName = native_tools.EntityTranslate(object);
    // 显示消息
    player.sendMessage([{ text: '<' }, userName, { text: '>与<' }, roleName, { text: '>已签订契约' }]);
    // 设置属性
    object.setDynamicProperty('entity:false_anchor_point', player.id);
    object.setDynamicProperty('entity:contract_user', player.id);
    object.addTag("is_Contract");
    /**
     * * 定义 粒子参数
     */
    const molang = new server.MolangVariableMap(); molang.setFloat('variable.size', 2); molang.setFloat('variable.direction', 0);
    // 播放 粒子效果
    native_tools.TrySpawnParticle(object.dimension, 'scripts:path_heart', math_tools.Vector.add(object.location, math_tools.Vector.CONSTANT_UP), molang);
    native_tools.TrySpawnParticle(object.dimension, 'minecraft:knockback_roar_particle', object.location);
    native_tools.TrySpawnParticle(object.dimension, 'minecraft:totem_particle', object.location);
};
/**
 * * 角色装备武器
 * 
 * @param {server.Entity} object - 进行契约的实体
 */
export function EquipWeapon(object: server.Entity) {
    /**
     * * 随机装备 - 护腿
     */
    const armorlegs = derived_tools.AnalysisWeight(data_entity.role_armor_legs).output;
    /**
     * * 随机装备 - 主手
     */
    const mainhand = derived_tools.AnalysisWeight(data_entity.role_main_hand).output;
    /**
     * * 随机装备 - 副手
     */
    const offhand = derived_tools.AnalysisWeight(data_entity.role_off_hand).output;
    // 检测实体是否具有装备
    server.system.runTimeout(
        () => {
            switch (object.hasComponent('minecraft:is_chested')) {
                case true:
                    // 添加 随机装备
                    server.system.runTimeout(() => object.runCommand(`replaceitem entity @s slot.weapon.mainhand 0 ${mainhand}`), 2);
                    server.system.runTimeout(() => object.runCommand(`replaceitem entity @s slot.weapon.offhand 0 ${offhand}`), 4);
                    server.system.runTimeout(() => object.runCommand(`replaceitem entity @s slot.armor.legs 0 ${armorlegs}`), 8);
                    break;

                default:
                    server.system.runTimeout(() => object.runCommand('replaceitem entity @s slot.weapon.mainhand 0 air'), 2);
                    server.system.runTimeout(() => object.runCommand('replaceitem entity @s slot.weapon.offhand 0 air'), 4);
                    server.system.runTimeout(() => object.runCommand('replaceitem entity @s slot.armor.legs 0 air'), 8);
                    break;
            }
        }, 5
    );
};
/**
 * * 实体阵亡后紧急保存的数据
 * 
 * @param {server.Entity} object - 进行契约的实体
 */
export function EntityConstruction(object: server.Entity) {
    /** 
     * * 创建 物品对象 - 星月诗篇
     */
    const record = new server.ItemStack('item_voucher:moon_and_stars');
    /**
     * * 复制实体坐标
     */
    const anchor_0 = math_tools.Vector.copy(object.location);
    /**
     * * 复制实体坐标
     */
    const anchor_1 = math_tools.Vector.add(anchor_0, { x: 0, y: 2, z: 0 });
    /**
     * * 粒子参数
     */
    const molang = new server.MolangVariableMap();
    /**
     * * 玩家列表
     */
    const players = server.world.getPlayers().filter(player => object.getDynamicProperty('entity:contract_user') === player.id);
    /**
     * * 物品名称
     */
    const name = '§c极限档案 - §d';
    /**
     * * 物品词缀
     */
    const lore = [
        `类型: ${object.typeId}`,
        `名称: ${object.nameTag}`,
        `坐标: ${math_tools.Vector.toString(object.location)}`,
        `维度: ${object.dimension.id}`,
        "§u___________________",
        "使用时, 请在心中默念:",
        "隐藏着< 元素力量 >的符纸啊",
        "在我面前显示你真正的力量!",
        `我以 ${players[0]?.nameTag} 之名命令你`,
        "—— 封印解除! ૮₍ ᵕoᵕ₎ა"
    ];
    // 设置 粒子尺寸
    molang.setFloat('variable.size', 4);
    // 播放 蝴蝶特效
    molang.setFloat('variable.direction', 3);
    native_tools.TrySpawnParticle(object.dimension, 'scripts:path_butterfly', anchor_0, molang);
    // 播放 圆环特效
    molang.setFloat('variable.direction', 0);
    native_tools.TrySpawnParticle(object.dimension, 'scripts:path_round', anchor_1, molang);
    // 播放 四芒星特效
    native_tools.TrySpawnParticle(object.dimension, 'scripts:path_diamond', anchor_1, molang);
    // 封印实体
    derived_tools.UnloadInventoryAndPackage(object, players[0] ?? server.world.getPlayers()[0], record, name, lore);
};
/**
 * * 玩家死亡后, 记录玩家死亡位置
 * 
 * @param {server.Player} object - 触发死亡事件的玩家对象
 */
export function PlayerDie(object: server.Player) {
    /**
     * * 坐标锚点
     */
    const anchor = {
        location: math_tools.Vector.floor(object.location),
        dimension: object.dimension.id
    };
    /**
     * * 玩家死亡点
     */
    const dieSpot = JSON.stringify(anchor);
    // 保存 死亡点
    object.setDynamicProperty('road_sign:死亡点', dieSpot);
};
/**
 * * 玩家进入 虚空野蜂塔
 * 
 * @param {server.Player} player - 执行事件的玩家对象
 */
export function EnterVacantSpaceWaspTower(player: server.Player) {
    /**
     * * 获取 游戏规则
     */
    const rule = server.world.getDynamicProperty('game_rules:regenerate.vacant_space_wasp_tower') ?? true;
    /**
     * * 坐标映射值
     */
    const mapping: server.Vector3 = { x: 500, y: 16, z: 500 };
    /**
     * * 进行结构生成的维度
     */
    const dimension = server.world.getDimension('minecraft:the_end');
    /**
     * * 定义 坐标锚点
     */
    const anchor = JSON.stringify({ location: mapping, dimension: dimension.id });
    /**
     * * 定义 相机参数
     */
    const camera = player.camera;
    /**
     * * 定义 摄像机终点坐标
     */
    const endPoint = math_tools.Vector.add(mapping, { x: 48, y: 64, z: 48 });
    /**
     * * 获取 玩家背包
     */
    const container = player.getComponent('inventory')?.container;
    /**
     * * 定义 粒子参数
     */
    const molang = new server.MolangVariableMap();
    // 触发新手礼包
    if (container) DonationInitialGift(player, container);
    // 给与 玩家 新手保护
    player.addEffect("invisibility", 1800, { amplifier: 1, showParticles: false });
    player.addEffect("resistance", 1800, { amplifier: 4, showParticles: false });
    // 播放引导文本
    derived_tools.PlayPrompt(player, "生成虚空野蜂塔");
    // 传送玩家到野蜂塔
    player.teleport(mapping, { dimension });
    // 清除 摄像机动画
    server.system.runTimeout(() => camera.clear(), 95);
    // 设置 摄像机位移
    server.system.runTimeout(() => camera.setCamera('minecraft:free', { location: endPoint, facingLocation: player.location, easeOptions: { easeTime: 3 } }), 20);
    // 设置 动态属性-野蜂塔坐标
    server.system.runTimeout(() => player.setDynamicProperty('road_sign:虚空野蜂塔', anchor), 20);
    // 播放剧情文本
    server.system.runTimeout(() => player.sendMessage({ translate: 'speak.crystal.plot_obsidianWaspTower_0' }), 100);
    server.system.runTimeout(() => player.sendMessage({ translate: 'speak.crystal.plot_obsidianWaspTower_1' }), 200);
    server.system.runTimeout(() => player.sendMessage({ translate: 'speak.crystal.plot_obsidianWaspTower_2' }), 300);
    server.system.runTimeout(() => player.sendMessage({ translate: 'speak.crystal.plot_obsidianWaspTower_3' }), 400);
    server.system.runTimeout(() => player.sendMessage({ translate: 'speak.crystal.plot_obsidianWaspTower_4' }), 500);
    server.system.runTimeout(() => player.sendMessage({ translate: 'speak.crystal.plot_obsidianWaspTower_5' }), 600);
    server.system.runTimeout(() => player.sendMessage({ translate: 'speak.crystal.plot_obsidianWaspTower_6' }), 800);
    server.system.runTimeout(() => player.sendMessage({ translate: 'speak.crystal.plot_obsidianWaspTower_7' }), 1000);
    server.system.runTimeout(() => player.sendMessage({ translate: 'speak.crystal.plot_obsidianWaspTower_8' }), 1150);
    // 播放音效
    server.system.runTimeout(() => player.playSound('speak.crystal.plot_obsidianWaspTower_0'), 100);
    server.system.runTimeout(() => player.playSound('speak.crystal.plot_obsidianWaspTower_1'), 200);
    server.system.runTimeout(() => player.playSound('speak.crystal.plot_obsidianWaspTower_2'), 300);
    server.system.runTimeout(() => player.playSound('speak.crystal.plot_obsidianWaspTower_3'), 400);
    server.system.runTimeout(() => player.playSound('speak.crystal.plot_obsidianWaspTower_4'), 500);
    server.system.runTimeout(() => player.playSound('speak.crystal.plot_obsidianWaspTower_5'), 600);
    server.system.runTimeout(() => player.playSound('speak.crystal.plot_obsidianWaspTower_6'), 800);
    server.system.runTimeout(() => player.playSound('speak.crystal.plot_obsidianWaspTower_7'), 1000);
    server.system.runTimeout(() => player.playSound('speak.crystal.plot_obsidianWaspTower_8'), 1150);
    // 设定射线类型
    molang.setFloat('variable.type', 0);
    // 设定射线方向
    molang.setVector3('variable.direction', math_tools.Vector.CONSTANT_UP);
    // 播放粒子特效
    server.system.runTimeout(() => GuideLightBeam(player, molang), 200);
    server.system.runTimeout(() => GuideLightBeam(player, molang), 400);
    server.system.runTimeout(() => GuideLightBeam(player, molang), 600);
    server.system.runTimeout(() => GuideLightBeam(player, molang), 800);
    // 判断是否生成结构
    if (rule === false) return;
    /**
     * * 获取 建筑结构
     */
    const template = server.world.structureManager.get('mystructure:vacant_space_wasp_tower');
    /**
     * * 定义 坐标基准点
     */
    const reference = math_tools.Vector.add(mapping, { x: -40, y: -9, z: -25 });
    // 检测 建筑结构
    if (!template) return player.sendMessage([native_tools.EntityTranslate(player), { text: '-> 未能获取到<§l§9 末地蜂塔 §r>的结构数据文件' }]);
    // 放置 建筑结构
    server.world.structureManager.place(template, dimension, reference);
    // 设置 游戏规则
    if (rule == true) server.world.setDynamicProperty('game_rules:regenerate.vacant_space_wasp_tower', false);
};
/**
 * * 诸界道标 指引光束 粒子特效
 */
function GuideLightBeam(player: server.Player, molang: server.MolangVariableMap) {
    // 检测 玩家是否在末地
    if (player.dimension.id !== 'minecraft:the_end') return;
    // 构建 动画效果
    player.spawnParticle('scripts:path_ray', { x: 504.5, y: 13, z: 491.5 }, molang);
    player.spawnParticle('scripts:path_ray', { x: 504.5, y: 13, z: 508.5 }, molang);
};
/**
 * * 领取 新手礼包
 * 
 * @param player - 领取新手礼包的玩家对象
 * 
 * @param container - 玩家背包
 */
function DonationInitialGift(player: server.Player, container: server.Container) {
    /**
     * * 涤尽铅华 物品对象
     */
    const pureness = new server.ItemStack("item_prop:reduction_pureness");
    /**
     * * 精灵结契 物品对象
     */
    const contract = new server.ItemStack("item_literature:faerie_contract");
    /**
     * * 源能秘典 物品对象
     */
    const energy = new server.ItemStack("item_literature:source_energy");
    /**
     * * 百灵绘卷 物品对象
     */
    const paper = new server.ItemStack("item_voucher:chorus_picture");
    /**
     * * 获取 空闲格子数量
     */
    const emptySlots = container?.emptySlotsCount ?? 0;
    /**
     * * 坐标映射值
     */
    const mapping: server.Vector3 = { x: 500, y: 16, z: 500 };
    // 设置 物品描述
    pureness.setLore(
        [
            "§u___________________",
            "跨维度旅行总是充满了各种难以预料的危险",
            "有的时候, 将风险交由一人承担",
            "并非推卸责任, 而是一种明智的选择 !"
        ]
    );
    paper.setLore(
        [
            "§u___________________",
            "此物是< 领航者 >许诺众生的福利",
            "到< 主世界 >使用看看吧 ?"
        ]
    );
    contract.setLore(
        [
            "§u___________________",
            "这是< 琉璃 >赠与你的礼物",
            "或许是希望你优先选择她 ?"
        ]
    );
    energy.setLore(
        [
            "§u___________________",
            "初始的 指引 与 向导",
            "一本或许 有用 又或许 没用 的书籍",
            "除了最本质的资料外, 似乎又记载了一些别的信息?"
        ]
    );
    // 判断玩家背包是否具有足够的空间
    if (emptySlots < 3) {
        server.system.runTimeout(() => native_tools.TrySpawnItem(player.dimension, paper, mapping), 50);
        server.system.runTimeout(() => native_tools.TrySpawnItem(player.dimension, energy, mapping), 70);
        server.system.runTimeout(() => native_tools.TrySpawnItem(player.dimension, contract, mapping), 90);
        server.system.runTimeout(() => native_tools.TrySpawnItem(player.dimension, pureness, mapping), 110);
    }
    else {
        server.system.runTimeout(() => container?.addItem(paper), 50);
        server.system.runTimeout(() => container?.addItem(energy), 70);
        server.system.runTimeout(() => container?.addItem(pureness), 90);
        server.system.runTimeout(() => container?.addItem(contract), 110);
    };
};
/**
 * * 实体生成日期表
 * 
 * @param {string} type - 等待生成的实体类型
 * 
 * @param {number} time - 生成间隔时间(游戏日)
 * 
 * @param {server.RawMessage} title - 显示的标题
 * 
 * @param {string} sound - 播放的音效
 */
export function GenerateOnSchedule(type: string, time: number, title: server.RawMessage, sound: string) {
    /**
     * * 日历计时值
     */
    const calendar = server.world.getDynamicProperty('generate_on_schedule:' + type) as number ?? 1;
    /**
     * * 获取 实体刷新日历
     */
    const convert = Math.floor(server.world.getDay() / time);
    // 检测是否满足刷新条件
    if (convert < calendar) return;
    /**
     * * 获取 全部玩家
     */
    const players = server.world.getPlayers();
    /**
     * * 获取 随机玩家
     */
    const player = players[math_tools.Random({ min: 0, max: players.length - 1 }, true)];
    /**
     * * +-32 随机值
     */
    const random = () => math_tools.Random({ max: 32, min: -32 });
    /**
     * * 随机偏移坐标
     */
    const offset = math_tools.Vector.add(player.location, { x: random(), y: 0, z: random() });
    /**
     * * 获取 随机有效坐标
     */
    const anchor = player.dimension.getTopmostBlock(offset)?.above(2) ?? player.location;
    // 刷新实体生成日历
    server.world.setDynamicProperty('generate_on_schedule:' + type, convert + 1);
    // 播放音效
    server.system.runTimeout(() => player.playSound(sound), 20);
    // 显示标题
    server.system.runTimeout(() => player.onScreenDisplay.setTitle(title), 40);
    // 生成实体
    server.system.runTimeout(() => native_tools.TrySpawnEntity(player.dimension, type, anchor), 60);
    // 路径规划
    achieve_plan.PathExecute.Create('基于日期生成实体-' + type, 1,
        {
            location_group: [player.getHeadLocation(), anchor],
            particles: ['constant:prompt_route'],
            dimension: player.dimension,
            cooldown: 1,
            speed: 1,
        }
    );
};
/**
 * * 隧龙列车运行事件
 * 
 * @param {server.Entity} entity - 隧龙列车实体
 * 
 * @param {string} type - 列车事件类型
 */
export function TunnelDragonTravel(entity: server.Entity, type: string) {
    /**
     * * 获取 列车能量
     */
    const energy = entity.getDynamicProperty('energy:offline_vehicle_power') as number ?? 3500;
    // 基于事件类型执行细分操作
    switch (type) {
        // 列车行驶
        case 'train_travel':
            if (energy >= 200) {
                /**
                 * * 光照放置令牌
                 */
                const token = achieve_plan.ControlEventTrigger.EntityToken('隧龙列车-光照方块', entity, 45);
                // 触发 数据驱动 实体事件
                entity.triggerEvent('entity_event:travel');
                // 检测光照令牌是否申请成功
                if (!token) return;
                // 消耗列车能量
                entity.setDynamicProperty('energy:offline_vehicle_power', energy - 200);
                /**
                 * * 定义 坐标基准点
                 */
                const anchor = math_tools.Vector.relativeOffset(entity.location, entity.getViewDirection(), { front: -4, right: 0, above: 0 });
                /**
                 * * 方块状态-灵魂火把
                 */
                const permutation = server.BlockPermutation.resolve('minecraft:soul_torch');
                /**
                 * * 转化为光源的预备方块
                 */
                const block = entity.dimension.getBlock(anchor);
                // 如果 方块为空气 就转换为 灵魂火把
                if (block?.isAir) block.setPermutation(permutation);
            }
            else {
                /**
                 * * 能源耗尽令牌
                 */
                const token = achieve_plan.ControlEventTrigger.EntityToken('隧龙列车-能源不足', entity, 200);
                // 检测能源耗尽令牌是否申请成功
                if (!token) return;
                /**
                 * * 获取 附近的玩家
                 */
                const players = entity.dimension.getPlayers({ maxDistance: 32, location: entity.location });
                /**
                 * * 编辑消息通知
                 */
                const message: server.RawMessage[] = [
                    native_tools.EntityTranslate(entity),
                    { text: ': 能源不足, 列车无法继续运行 :' },
                    { text: math_tools.Vector.toString(entity.location) }
                ];
                // 推送消息
                players.forEach(player => player.sendMessage(message))
            }
            break;

        // 仓储管理
        case 'inventory_filter':
            break;

        // 扩展模块
        case 'extend_module': TunnelDragonExtendModule(entity); break;

        // 载具回收
        case 'recycling': TunnelDragonRecycling(entity); break;

        // 未知
        default: break;
    }
};
/**
 * * 隧龙列车回收事件
 * 
 * @param {server.Entity} entity - 列车实体
 */
function TunnelDragonRecycling(entity: server.Entity) {
    /** 
     * * 武装召集
     */
    const item = new server.ItemStack('item_armament:call_tunnel_dragon_guide');
    /**
     * * 获取 玩家
     */
    const player = server.world.getEntity(entity.getDynamicProperty('entity:contract_user') as string);
    /**
     * * 获取 玩家背包
     */
    const container = player?.getComponent('inventory')?.container;
    // 删除 隧龙列车
    if (player) derived_tools.UnloadInventoryAndPackage(entity, player as server.Player, item, '§l§q载具回收§r - ', []);
    // 删除 控制器物品
    if (container) native_tools.DeleteItemStack(container, new server.ItemStack('item_prop:mechanized_operation'));
};
/**
 * * 隧龙列车扩展模块
 * 
 * @param {server.Entity} entity - 列车实体
 */
function TunnelDragonExtendModule(entity: server.Entity) {
    /**
     * * 列车模块查询条件
     */
    const options: server.EntityQueryOptions = {
        families: ['train_parts'],
        location: entity.location,
        maxDistance: 3
    };
    /**
     * * 获取 列车部件
     */
    const trainParts = entity.dimension.getEntities(options);
    /**
     * * 获取 玩家
     */
    const player = server.world.getEntity(entity.getDynamicProperty('entity:contract_user') as string) as server.Player;
    /** 
     * * 定义了 窗口界面 的 标题 
     */
    const title: server.RawMessage = {
        text: "<§9§o§l 隧龙领航者-隧道掘进列车 §r>§2扩展组件"
    };
    /** 
     * * 定义了 窗口界面 的 选项
     */
    const option: server.RawMessage[] = [
        { text: '<§5§o§l 单人列车沙发 §5>§r' },
        { text: '<§5§o§l 基础列车货架 §5>§r' }
    ];
    /** 
     * * 定义了 窗口界面 的 表单对象
     */
    const display = new server_ui.ActionFormData()
        .title(title)
        .button(option[0], "textures/项目图标/神机操持/单人沙发")
        .button(option[1], "textures/项目图标/神机操持/列车货架")
    if (!player || trainParts.length >= 4) return player.sendMessage([native_tools.EntityTranslate(player), { text: '-> 当前列车的<§l§9 扩展插槽 §r>已满载, 无法继续创建<§l§9 扩展组件 §r>' }]);
    // 显示窗口界面
    display.show(player as server.Player).then(
        option => {
            if (option.canceled) return;
            switch (option.selection) {
                // 沙发
                case 0: native_tools.TrySpawnEntity(entity.dimension, 'entity_machine:tunnel_dragon_couch', entity.location); break;
                // 货架
                case 1: native_tools.TrySpawnEntity(entity.dimension, 'entity_machine:tunnel_dragon_inventory', entity.location); break;
            }
        }
    )
};
/**
 * * 区块连锁
 * 
 * @param {server.PlayerBreakBlockAfterEvent} eventData 区块连锁 所需的 事件参数
 * 
 * @param {string} type 区块连锁 类型
 */
export function BlockChainEvent(eventData: server.PlayerBreakBlockAfterEvent, type: string) {
    /**
     * * 被挖掘的方块的标识符
     */
    const blockID = eventData.brokenBlockPermutation.type.id;
    /**
     * * 进行挖掘的位置
     */
    const location = eventData.block.location;
    /**
     * * 进行挖掘的维度
     */
    const dimension = eventData.dimension;
    /**
     * * 玩家对象
     */
    const player = eventData.player;
    /** 
     * * 获取 玩家背包
     */
    const container = player.getComponent('minecraft:inventory')?.container;
    /**
     * * 进行挖掘的物品
     */
    const item = eventData.itemStackAfterBreak;
    /**
     * * 高度
     */
    const height = player.getDynamicProperty('block_chain:height') as number;
    /**
     * * 深度
     */
    const depth = player.getDynamicProperty('block_chain:depth') as number;
    /**
     * * 范围
     */
    const range = player.getDynamicProperty('block_chain:range') as number;
    /**
     ** 挖掘方块理应消耗的耐久度
     */
    const waste = (Math.abs(depth) + height) * (range * 2);
    /**
     * * 耐久度组件
     */
    const durability = item?.getComponent('minecraft:durability'); if (!durability) return;
    /**
     ** 耐久度剩余耐久度
     */
    const surplus = durability.maxDurability - durability.damage;
    // 判断 是否满足条件
    if (!item || !data_item.is_tool.has(item.typeId)) return;
    // 判断 耐久度是否足够
    if (waste >= surplus) return player.sendMessage([native_tools.ItemTranslate(item), { text: ' -> 耐久度不足, 无法连锁' }]);
    // 判断 连锁触发条件
    switch (type) {
        case '潜行': if (!player.isSneaking) return; break;

        case '始终': break;

        default: return;
    };
    // 为 玩家 添加状态效果
    player.addEffect('mining_fatigue', 200, { amplifier: 29, showParticles: false });
    player.addEffect('hunger', 200, { amplifier: 29, showParticles: false });
    /**
     * * 定义 路径事件
     */
    const moveEvent = (args: data_format.ROUTE_ANNEX_ARGS) => {
        /**
         * * 获取 方块
         */
        const getBlock = args.dimension.getBlock(args.location);
        //执行路径事件的功能
        if (getBlock?.typeId === blockID) {
            // 执行填充方块命令
            args.dimension.runCommand(`fill ${args.location.x} ${args.location.y} ${args.location.z} ${args.location.x} ${args.location.y} ${args.location.z} air [] destroy`)
            /**
             * * 定义 掉落物 的 参数
             */
            const itemOptions: server.EntityQueryOptions = {
                location: args.location,
                type: "minecraft:item",
                maxDistance: 4
            };
            /**
             * * 定义 经验球 的 参数
             */
            const expOptions: server.EntityQueryOptions = {
                location: args.location,
                type: "minecraft:xp_orb",
                maxDistance: 4
            };
            /**
             * * 获取 掉落物 与 经验球 的 实体
             */
            const select = [
                ...args.dimension.getEntities(itemOptions),
                ...args.dimension.getEntities(expOptions)
            ];
            // 获取附近的掉落物
            select.forEach(entity => entity.teleport(player.getHeadLocation(), { dimension: player.dimension }));
        }
        // 继续循环
        return true
    };
    /**
     * * 立方体绘制 的 起始顶点
     */
    const start = math_tools.Vector.add(location, { x: range, y: depth, z: range });
    /**
     * * 立方体绘制 的 结束顶点
     */
    const done = math_tools.Vector.add(location, { x: -range, y: height, z: -range });
    // 创建 路径执行计划
    achieve_plan.PathExecute.CreateForCube(
        '区块连锁-路径执行',
        {
            particles: ['constant:track_color_yellow'],
            location_group: [],
            dimension,
            cooldown: 1,
            speed: 1,
            offset: math_tools.Vector.CONSTANT_HALF,
            on_move: moveEvent,
        },
        start, done, 0.25
    );
    // 消耗耐久值
    durability.damage += waste;
    // 置换物品
    if (container) container.setItem(player.selectedSlotIndex, item);
};
/**
 * * 重新设置世界规则
 * 
 * @param {server.Dimension} dimension - 维度对象
 */
export function ReviseWorldRules(dimension: server.Dimension) {
    // 禁止发送命令反馈
    dimension.runCommandAsync('gamerule sendcommandfeedback false');
    // 关闭命令方块输出
    dimension.runCommandAsync('gamerule commandblockoutput false');
    // 开启立即重生
    dimension.runCommandAsync('gamerule doimmediaterespawn true');
    // 关闭边境效果显示
    dimension.runCommandAsync('gamerule showBorderEffect false');
    // 开启坐标显示
    dimension.runCommandAsync('gamerule showcoordinates true');
    // 开启游戏天数显示
    dimension.runCommandAsync('gamerule showDaysPlayed true');
    // 开启死亡后保留物品栏
    dimension.runCommandAsync('gamerule keepinventory true');
    // 开启生物破坏环境
    dimension.runCommandAsync('gamerule mobgriefing true');
    // 设置游戏难度为困难
    dimension.runCommandAsync('difficulty hard');
};
/**
 * * 实体遭受攻击后 事件
 * 
 * @param {server.Entity} target - 被命中的实体
 * 
 * @param {server.EntityDamageSource} source - 伤害来源
 * 
 * @param {server.Entity} entity - 发起攻击的实体
 * 
 * @param {number} damage - 伤害数值
 */
export function EntityUnderAttack(target: server.Entity, source: server.EntityDamageSource, entity: server.Entity, damage: number) {
    // 检测是否为 玩家类型
    if (target instanceof server.Player) return;
    // 基于实体类型进行分支
    switch (target.typeId) {
        case 'minecraft:ender_dragon': passive_component.EnhanceEnderDragon(target, entity, damage, source.cause); break;

        case 'entity_machine:wasp_emperor': passive_component.WaspReinforce(target); break;

        case 'entity_chase:jasmine': passive_component.PrayerOfHundredFlowers(target); break;

        case 'entity_machine:whale_emperor': passive_component.DefineOfWhaleDamage(target, entity); break;

        case 'entity_machine:whale_detection': passive_component.DefineOfWhaleAdjudication(entity); break;

        default: break;
    }
}
/**
 * * 玩家遭受攻击后 事件
 * 
 * @param {server.Entity} target - 被命中的实体
 * 
 * @param {server.EntityDamageSource} source - 伤害来源
 * 
 * @param {server.Entity} entity - 发起攻击的实体
 */
export function PlayersUnderAttack(target: server.Entity, entity: server.Entity) {
    // 检测是否为 玩家类型
    if (!(target instanceof server.Player)) return;
    /**
     * * 装备容器
     */
    const equippable = target.getComponent('minecraft:equippable');
    // 检测装备容器
    if (!equippable) return;
    /**
     * * 物品槽位
     */
    const itemSlot: server.EquipmentSlot[] = Object.values(server.EquipmentSlot);
    /**
     * * 物品数组
     */
    const items = itemSlot.map(slot => equippable.getEquipment(slot));
    // 玩家遭受攻击后 触发 实体被动事件
    passive_component.EntityHurtPlayerAfterOddsTrigger(target, entity, equippable, items, itemSlot);
    // 玩家遭受攻击后 触发 物品被动事件
    items.forEach(
        (item, index) => {
            // 检测 是否存在 物品对象
            if (!item) return;
            // 检测 物品类型
            switch (item.typeId) {
                case 'item_tool:magic_crystal_shield': tool_component.MagicCrystalShield(target, item, itemSlot[index]); break;

                default: break;
            }
        }
    )
};
/**
 * * 玩家发动攻击后 事件
 * 
 * @param {server.Entity} target - 被命中的实体
 * 
 * @param {server.EntityDamageSource} source - 伤害来源
 * 
 * @param {server.Entity} entity - 发起攻击的实体
 */
export function PlayersLaunchAttacks(target: server.Entity, source: server.EntityDamageSource, entity: server.Entity) {
    // 检测是否为 玩家类型
    if (!(entity instanceof server.Player)) return;
    /**
     * * 装备容器
     */
    const equippable = entity.getComponent('minecraft:equippable');
    /**
     * * 物品槽位
     */
    const itemSlot: server.EquipmentSlot[] = [
        server.EquipmentSlot.Mainhand,
        server.EquipmentSlot.Offhand
    ];
    /**
     * * 物品数组
     */
    const itemSelect = itemSlot.map(slot => equippable?.getEquipment(slot));
    // 遍历 物品对象数组
    itemSelect.forEach(
        item => {
            // 检测 是否存在 物品对象
            if (!item) return;
            // 检测 物品类型
            if (source.cause == 'projectile') {
                switch (item.typeId) {
                    case 'item_tool:magic_crystal_bow': tool_component.BowHitAfter(entity, target); break;

                    default: break;
                }
            }
        }
    )
};
/**
 * * 死亡后触发奖励
 * 
 * @param {server.Entity} target - 被击杀的实体
 * 
 * @param {server.Entity} entity - 击杀者
 */
export function createRewardsAfterDeath(target: server.Entity, entity: server.Entity) {
    /**
     * * 死亡的实体是否为< 地方传奇 >
     */
    const intel = data_entity.area_legend.get(target.typeId);
    /**
     * * 击杀者 的 战斗经验
     */
    const experience = entity.getDynamicProperty('entity:experience') as number ?? 0;
    /**
     * * 元素黑名单
     */
    const blacklist = new Set<data_format.RUNE_TYPE>(["rune_black", "rune_white", "rune_void"]);
    /**
     * * 击杀者 的 维度
     */
    const dimension = target.dimension;
    /**
     * * 击杀者 的 属性面板
     */
    const state = power_property.GetProperty(entity);
    /**
     * * 验证 是否 满足 发放条件
     */
    const enable = derived_tools.IsEnable((experience / data_entity.experience_improve) + 15);
    // 生成 对应的魔晶石
    if (enable && !blacklist.has(state.self_rune)) native_tools.TrySpawnItem(dimension, new server.ItemStack('item_crystal:' + state.self_rune.split('_')[1] + '_energy'), target.location);
    // 给与击杀者经验
    if (experience / data_entity.experience_improve <= data_entity.max_experience) entity.setDynamicProperty('entity:experience', experience + Math.floor((intel ?? 1) / 10) + 1);
    // 验证 是否满足发放条件
    if (!intel || !derived_tools.IsEnable(intel)) return;
    native_tools.TrySpawnItem(dimension, new server.ItemStack('item_voucher:chorus_picture'), target.location);
};
/**
 * * 在死亡后触发功能
 * 
 * @param {server.Entity} entity - 死亡的 实体
 */
export function FunctionsPerformedAfterDeath(entity: server.Entity) {
    switch (entity.typeId) {
        case 'minecraft:player': PlayerDie(entity as server.Player); break;

        case 'entity_machine:wasp_support': passive_component.WaspClusterCrash(entity); break;

        default: break;
    };
};